View Javadoc

1   // CircularAddressQueue.java, created Aug 3, 2004 3:29:21 AM by joewhaley
2   // Copyright (C) 2004 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Allocator;
5   
6   import joeq.Memory.Address;
7   import joeq.Memory.HeapAddress;
8   import joeq.Runtime.Debug;
9   import joeq.Runtime.SystemInterface;
10  import jwutil.util.Assert;
11  
12  /***
13   * An implementation of an address queue that uses a circular buffer.
14   * 
15   * @author John Whaley
16   * @version $Id: CircularAddressQueue.java 1941 2004-09-30 03:37:06Z joewhaley $
17   */
18  public class CircularAddressQueue implements AddressQueue {
19      
20      public static final boolean TRACE = false;
21      
22      /***
23       * Size of block (in words) to allocate when we need more space
24       * in a queue.
25       */
26      public static int QUEUE_WORDS = 262144;
27      
28      /***
29       * Queue pointers.
30       */
31      HeapAddress queueStart, queueEnd;
32      
33      /***
34       * Pointers to start and end of memory block.
35       */
36      HeapAddress blockStart, blockEnd;
37      
38      /***
39       * Create a new CircularAddressQueue.
40       * Does not allocate any memory yet.
41       */
42      public CircularAddressQueue() {
43          super();
44      }
45      
46      /* (non-Javadoc)
47       * @see joeq.Allocator.AddressQueue#free()
48       */
49      public void free() {
50          if (TRACE) Debug.writeln("Freeing work queue.");
51          if (!blockStart.isNull()) {
52              SystemInterface.sysfree(blockStart);
53              blockStart = blockEnd = queueStart = queueEnd = HeapAddress.getNull();
54          }
55      }
56      
57      /* (non-Javadoc)
58       * @see joeq.Allocator.AddressQueue#growQueue(int)
59       */
60      public void growQueue(int words) {
61          // todo: use realloc here.
62          if (true) Debug.writeln("Growing work queue to size ", words * HeapAddress.size());
63          HeapAddress new_queue = (HeapAddress) SystemInterface.syscalloc(words * HeapAddress.size());
64          if (TRACE) Debug.writeln("New Queue start: ", new_queue);
65          if (new_queue.isNull())
66              HeapAllocator.outOfMemory();
67          if (TRACE) Debug.writeln("Queue start: ", queueStart);
68          if (TRACE) Debug.writeln("Queue end: ", queueEnd);
69          if (TRACE) Debug.writeln("Block start: ", blockStart);
70          if (TRACE) Debug.writeln("Block end: ", blockEnd);
71          int size = queueEnd.difference(queueStart);
72          if (size > 0) {
73              if (TRACE) Debug.writeln("Current size ", size);
74              Assert._assert(words * HeapAddress.size() > size);
75              SystemInterface.mem_cpy(new_queue, queueStart, size);
76          } else {
77              if (TRACE) Debug.writeln("Pointers are flipped");
78              int size2 = blockEnd.difference(queueStart);
79              if (TRACE) Debug.writeln("Size of first part: ", size2);
80              SystemInterface.mem_cpy(new_queue, queueStart, size2);
81              int size3 = queueEnd.difference(blockStart);
82              if (TRACE) Debug.writeln("Size of second part: ", size3);
83              SystemInterface.mem_cpy(new_queue.offset(size2), blockStart, size3);
84              size = size2 + size3;
85          }
86          if (TRACE) Debug.writeln("Freeing old queue");
87          SystemInterface.sysfree(blockStart);
88          queueStart = blockStart = new_queue;
89          blockEnd = (HeapAddress) blockStart.offset(words * HeapAddress.size());
90          queueEnd = (HeapAddress) queueStart.offset(size);
91          if (true) Debug.writeln("New Block end:", blockEnd);
92          if (true) Debug.writeln("New Queue end:", queueEnd);
93      }
94      
95      /* (non-Javadoc)
96       * @see joeq.Allocator.AddressQueue#size()
97       */
98      public int size() {
99          int size = queueEnd.difference(queueStart);
100         if (size < 0) {
101             size = blockEnd.difference(queueStart) +
102                    queueEnd.difference(blockStart);
103         }
104         return size / HeapAddress.size();
105     }
106     
107     /* (non-Javadoc)
108      * @see joeq.Allocator.AddressQueue#space()
109      */
110     public int space() {
111         int size = queueEnd.difference(queueStart);
112         int space;
113         if (size < 0) {
114             space = -size;
115         } else {
116             space = blockEnd.difference(queueEnd) +
117                     queueStart.difference(blockStart);
118         }
119         return space / HeapAddress.size();
120     }
121     
122     /* (non-Javadoc)
123      * @see joeq.Allocator.AddressQueue#push(joeq.Memory.Address)
124      */
125     public void push(Address a) {
126         if (TRACE) Debug.writeln("Adding to queue: ", a);
127         if (space() <= HeapAddress.size()) {
128             // need a bigger work queue!
129             int size = blockEnd.difference(blockStart);
130             if (size == 0) size = QUEUE_WORDS;
131             else size = (QUEUE_WORDS *= 2);
132             growQueue(size);
133         }
134         if (TRACE) Debug.writeln("Adding at: ", queueEnd);
135         queueEnd.poke(a);
136         queueEnd = (HeapAddress) queueEnd.offset(HeapAddress.size());
137         if (queueEnd.difference(blockEnd) == 0) {
138             queueEnd = blockStart;
139             if (TRACE) Debug.writeln("Queue end pointer wrapped around to: ", queueEnd);
140         }
141         Assert._assert(queueEnd.difference(queueStart) != 0);
142     }
143     
144     /* (non-Javadoc)
145      * @see joeq.Allocator.AddressQueue#pull()
146      */
147     public Address pull() {
148         if (queueEnd.difference(queueStart) == 0) {
149             return HeapAddress.getNull();
150         }
151         if (TRACE) Debug.writeln("Pulling from: ", queueStart);
152         HeapAddress a = (HeapAddress) queueStart.peek();
153         queueStart = (HeapAddress) queueStart.offset(HeapAddress.size());
154         if (queueStart.difference(blockEnd) == 0) {
155             queueStart = blockStart;
156             if (TRACE) Debug.writeln("Queue start pointer wrapped around to: ", queueStart);
157         }
158         if (TRACE) Debug.writeln("Pulled from queue: ", a);
159         return a;
160     }
161     
162     /* (non-Javadoc)
163      * @see joeq.Allocator.AddressQueue#peek()
164      */
165     public Address peek() {
166         if (queueEnd.difference(queueStart) == 0) {
167             return HeapAddress.getNull();
168         }
169         Address a = (Address) queueStart.peek();
170         if (TRACE) Debug.writeln("Peeked from queue: ", a);
171         return a;
172     }
173 }